{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 介绍常用的 10 种视图，这些视图包括了散点图、折线图、直方图、条形图、箱线图、饼图、热力图、蜘蛛图、二元变量分布和成对关系"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 一、散点图\n",
    "\n",
    "1. 将两个变量的值显示在二维坐标中，适合展示两个变量之间的关系，\n",
    "2. Matplotlib工具中经常会用到 pyplot 这个工具包，包括了很多绘图函数，类似 Matlab 的绘图框架，画散点图，需要使用 plt.scatter(x, y, marker=None) 函数,x、y是坐标,marker代表标记的符号(“x”,“>”,“o”,默认None),可修改查看效果\n",
    "3. 除了 Matplotlib 外，也可以使用 Seaborn 进行散点图的绘制，使用 sns.jointplot(x, y, data=None, kind=‘scatter’) 函数,x、y 是 data 中的下标。data 就是要传入的数据，一般是 DataFrame 类型。kind取scatter，代表散点的意思,当然 kind 还可以取其他值\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模拟数据是随机的 1000 个点\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "N = 1000\n",
    "x = np.random.randn(N)\n",
    "y = np.random.randn(N)\n",
    "# 用Matplotlib画散点图\n",
    "plt.scatter(x, y,marker='x')\n",
    "plt.show()\n",
    "# 用Seaborn画散点图\n",
    "df = pd.DataFrame({'x': x, 'y': y})\n",
    "sns.jointplot(x=\"x\", y=\"y\", data=df, kind='scatter');\n",
    "plt.show()\n",
    "# Matplotlib 默认情况下呈现是长方形。而Seaborn呈现是正方形,而且不仅显示出了散点图，还给了这两个变量的分布情况"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 二、折线图\n",
    "\n",
    "1. 折线图一般用来表示数据随着时间变化的趋势\n",
    "2. Matplotlib 中，可用 plt.plot() 函数，需要提前把数据按照 x 轴的大小进行排序，要不画出来的折线图就无法按照 x 轴递增的顺序展示\n",
    "3. Seaborn 中，用 sns.lineplot (x, y, data=None) 函数。其中 x、y 是 data 中的下标。data 就是要传入的数据，一般是 DataFrame 类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "x = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]  # 表示年份\n",
    "y = [5, 3, 6, 20, 17, 16, 19, 30, 32, 35] # 随便取几个值\n",
    "# 使用Matplotlib画折线图\n",
    "plt.plot(x, y)\n",
    "plt.show()\n",
    "# 使用Seaborn画折线图\n",
    "df = pd.DataFrame({'x': x, 'y': y})\n",
    "sns.lineplot(x=\"x\", y=\"y\", data=df)\n",
    "plt.show()\n",
    "# 结果中可以看出这两个图示的结果是完全一样的，只是在 seaborn 中标记了 x 和 y 轴的含义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 三、直方图\n",
    "\n",
    "1. 直方图把横坐标等分成了一定数量的小区间，这个小区间也叫作“箱子”，然后在每个“箱子”内用矩形条（bars）展示该箱子的箱子数（也就是 y 值）\n",
    "2. Matplotlib 中，使用 plt.hist(x, bins=10) 函数，x 是一维数组，bins 代表箱子数量，默认是 10\n",
    "3. Seaborn 中，使用 sns.distplot(x, bins=10, kde=True) 函数。x 是一维数组，bins 代表箱子数量，kde 代表显示核密度估计，默认是 True。核密度估计是通过核函数来估计概率密度的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 绘制直方图的代码\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "a = np.random.randn(100)\n",
    "s = pd.Series(a) \n",
    "# 用Matplotlib画直方图\n",
    "plt.hist(s)\n",
    "plt.show()\n",
    "# 用Seaborn画直方图\n",
    "sns.distplot(s, kde=False)\n",
    "plt.show()\n",
    "sns.distplot(s, kde=True)\n",
    "plt.show()\n",
    "# 结果没有任何差别，其中最后一张图就是 kde 默认为 Ture 时的显示情况"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 四、条形图\n",
    "\n",
    "1. 如果说通过直方图可以看到变量的数值分布，那么条形图可以帮我们查看类别的特征。在条形图中，长条形的长度表示类别的频数，宽度表示类别\n",
    "2. Matplotlib 中，使用 plt.bar(x, height) 函数，其中参数 x 代表 x 轴的位置序列，height 是 y 轴的数值序列，也就是柱子的高度\n",
    "3. Seaborn 中，使用 sns.barplot(x=None, y=None, data=None) 函数。其中参数 data 为 DataFrame 类型，x、y 是 data 中的变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建了 x、y 两个数组，分别代表类别和类别的频数，然后用 Matplotlib 和 Seaborn 进行条形图的显示\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "x = ['Cat1', 'Cat2', 'Cat3', 'Cat4', 'Cat5']\n",
    "y = [5, 4, 8, 12, 7]\n",
    "# 用Matplotlib画条形图\n",
    "plt.bar(x, y)\n",
    "plt.show()\n",
    "# 用Seaborn画条形图\n",
    "sns.barplot(x, y)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 五、箱线图\n",
    "\n",
    "1. 箱线图由五个数值点组成：最大值 (max)、最小值 (min)、中位数 (median) 和上下四分位数 (Q3, Q1)。它可以帮我们分析出数据的差异性、离散程度和异常值等\n",
    "2. Matplotlib 中，使用 plt.boxplot(x, labels=None) 函数，其中参数 x 代表要绘制箱线图的数据，labels 是缺省值，可以为箱线图添加标签\n",
    "3.  Seaborn 中，使用 sns.boxplot(x=None, y=None, data=None) 函数。其中参数 data 为 DataFrame 类型，x、y 是 data 中的变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 生成 0-1 之间的 10*4 维度数据，然后分别用 Matplotlib 和 Seaborn 进行箱线图的展示\n",
    "# 数据准备\n",
    "# 生成0-1之间的10*4维度数据\n",
    "data=np.random.normal(size=(10,4)) \n",
    "lables = ['A','B','C','D']\n",
    "# 用Matplotlib画箱线图\n",
    "plt.boxplot(data,labels=lables)\n",
    "plt.show()\n",
    "# 用Seaborn画箱线图\n",
    "df = pd.DataFrame(data, columns=lables)\n",
    "sns.boxplot(data=df)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 六、饼图\n",
    "\n",
    "1. 在 Python 数据可视化中，饼图用的不算多，主要采用 Matplotlib 的 pie 函数实现\n",
    "2. 在Matplotlib 中，使用 plt.pie(x, labels=None) 函数，其中参数 x 代表要绘制饼图的数据，labels 是缺省值，可以为饼图添加标签"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 设置了 lables 数组，分别代表高中、本科、硕士、博士和其他几种学历的分类标签。nums 代表这些学历对应的人数\n",
    "import matplotlib.pyplot as plt\n",
    "# 数据准备\n",
    "nums = [25, 37, 33, 37, 6]\n",
    "labels = ['High-school','Bachelor','Master','Ph.d', 'Others']\n",
    "# 用Matplotlib画饼图\n",
    "plt.pie(x = nums, labels=labels)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 七、热力图\n",
    "\n",
    "1. 热力图是一种矩阵表示方法，其中矩阵中的元素值用颜色来代表，不同的颜色代表不同大小的值。通过颜色就能直观地知道某个位置上数值的大小。另外也可以将这个位置上的颜色，与数据集中的其他位置颜色进行比较\n",
    "2. 热力图是一种非常直观的多元变量分析方法，一般使用 Seaborn 中的 sns.heatmap(data) 函数，其中 data 代表需要绘制的热力图数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# 这里使用 Seaborn 中自带的数据集 flights，该数据集记录了 1949 年到 1960 年期间，每个月的航班乘客的数量\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "flights = sns.load_dataset(\"flights\")\n",
    "data=flights.pivot('year','month','passengers')\n",
    "# 用Seaborn画热力图\n",
    "sns.heatmap(data)\n",
    "plt.show()\n",
    "# 通过 seaborn 的 heatmap 函数，可以观察到不同年份，不同月份的乘客数量变化情况，其中颜色越浅的代表乘客数量越多"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 八、蜘蛛图\n",
    "\n",
    "1. 蜘蛛图是一种显示一对多关系的方法。在蜘蛛图中，一个变量相对于另一个变量的显著性是清晰可见的\n",
    "2. 假设想要给王者荣耀的玩家做一个战力图，指标一共包括推进、KDA、生存、团战、发育和输出。那该如何做呢？\n",
    "    - 需要使用 Matplotlib 来进行画图，首先设置两个数组：labels 和 stats。分别保存了这些属性的名称和属性值\n",
    "    - 因为蜘蛛图是一个圆形，需计算每个坐标的角度，然后对这些数值进行设置。当画完最后一个点后，需要与第一个点进行连线\n",
    "    - 因为需要计算角度，所以要准备 angles 数组\n",
    "    - 又因为需要设定统计结果的数值，所以要设定 stats 数组\n",
    "    - 并且需要在原有 angles 和 stats 数组上增加一位，也就是添加数组的第一个元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from matplotlib.font_manager import FontProperties  \n",
    "# 数据准备\n",
    "labels=np.array([u\"推进\",\"KDA\",u\"生存\",u\"团战\",u\"发育\",u\"输出\"])\n",
    "stats=[83, 61, 95, 67, 76, 88]\n",
    "# 画图数据准备，角度、状态值\n",
    "angles=np.linspace(0, 2*np.pi, len(labels), endpoint=False)\n",
    "stats=np.concatenate((stats,[stats[0]]))\n",
    "angles=np.concatenate((angles,[angles[0]]))\n",
    "# 用Matplotlib画蜘蛛图\n",
    "fig = plt.figure()  # 创建一个空白的 figure 对象(相当于画画前先准备一个空白的画板)\n",
    "ax = fig.add_subplot(111, polar=True) # 把画板划分成 1 行 1 列\n",
    "ax.plot(angles, stats, 'o-', linewidth=2) # 连线\n",
    "ax.fill(angles, stats, alpha=0.25) # 给图形上色\n",
    "# 设置中文字体\n",
    "# Matplotlib 对中文的显示不是很友好，因此设置了中文的字体 font，这个需要在调用前进行定义\n",
    "font = FontProperties(fname=r\"C:\\Windows\\Fonts\\simhei.ttf\", size=14)\n",
    "ax.set_thetagrids(angles * 180/np.pi, labels, FontProperties=font) # 在相应的位置上显示出属性名\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 九、二元变量分布\n",
    "\n",
    "1. 如果想要看两个变量之间的关系，就需要用到二元变量分布。当然二元变量分布有多种呈现方式，散点图就是一种二元变量分布\n",
    "2. 在 Seaborn 里，使用二元变量分布是非常方便的，直接使用 sns.jointplot(x, y, data=None, kind) 函数即可。其中用 kind 表示不同的视图类型：“kind=‘scatter’”代表散点图，“kind=‘kde’”代表核密度图，“kind=‘hex’ ”代表 Hexbin 图，它代表的是直方图的二维模拟\n",
    "3. 这里使用 Seaborn 中自带的数据集 tips，这个数据集记录了不同顾客在餐厅的消费账单及小费情况。代码中 total_bill 保存了客户的账单金额，tip 是该客户给出的小费金额。我们可以用 Seaborn 中的 jointplot 来探索这两个变量之间的关系"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 代码中用 kind 分别显示了散点图、核密度图和 Hexbin 图\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "tips = sns.load_dataset(\"tips\")\n",
    "print(tips.head(10))\n",
    "# 用Seaborn画二元变量分布图（散点图，核密度图，Hexbin图）\n",
    "sns.jointplot(x=\"total_bill\", y=\"tip\", data=tips, kind='scatter')\n",
    "sns.jointplot(x=\"total_bill\", y=\"tip\", data=tips, kind='kde')\n",
    "sns.jointplot(x=\"total_bill\", y=\"tip\", data=tips, kind='hex')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 十、成对关系\n",
    "\n",
    "1. 如果想要探索数据集中的多个成对双变量的分布，可以直接采用 sns.pairplot() 函数。它会同时展示出 DataFrame 中每对变量的关系，另外在对角线上，能看到每个变量自身作为单变量的分布情况。它可以说是探索性分析中的常用函数，可以很快帮助理解变量对之间的关系\n",
    "2. pairplot 函数的使用，就像在 DataFrame 中使用 describe() 函数一样方便，是数据探索中的常用函数\n",
    "3. 这里使用 Seaborn 中自带的 iris 数据集，这个数据集也叫鸢尾花数据集。鸢尾花可以分成 Setosa、Versicolour 和 Virginica 三个品种，在这个数据集中，针对每一个品种，都有 50 个数据，每个数据中包括了 4 个属性，分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。通过这些数据，需要你来预测鸢尾花卉属于三个品种中的哪一种"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "# 数据准备\n",
    "iris = sns.load_dataset('iris')\n",
    "# 用Seaborn画成对关系\n",
    "sns.pairplot(iris)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 这里用 Seaborn 中的 pairplot 函数来对数据集中的多个双变量的关系进行探索，如下图所示。从图上能看出，一共有 sepal_length、sepal_width、petal_length 和 petal_width4 个变量，它们分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度\n",
    "2. 下面这张图相当于这 4 个变量两两之间的关系。比如矩阵中的第一张图代表的就是花萼长度自身的分布图，它右侧的这张图代表的是花萼长度与花萼宽度这两个变量之间的关系\n",
    "`imgs/123.png`\n",
    "![](imgs/123.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 总结：\n",
    "\n",
    "- Python 可视化工具包 Matplotlib 和 Seaborn 工具包的关系就相当于 NumPy 和 Pandas 的关系。Seaborn 是基于 Matplotlib 更加高级的可视化库"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
